package com.miyake.dsp.ui;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.miyake.dsp.DspComposite;
import com.miyake.dsp.analyzer.FftSetting;
import com.miyake.dsp.circuit.RcSetting;
import com.miyake.dsp.converter.AbsoluteSetting;
import com.miyake.dsp.converter.DiffSetting;
import com.miyake.dsp.converter.LimiterSetting;
import com.miyake.dsp.converter.LogSetting;
import com.miyake.dsp.converter.NormalizeSetting;
import com.miyake.dsp.converter.OffsetSetting;
import com.miyake.dsp.convolution.ConvolutionImplScilab;
import com.miyake.dsp.convolution.ConvolutionSetting;
import com.miyake.dsp.filter.FilterSetting;
import com.miyake.dsp.generator.NoiseGenerator;
import com.miyake.dsp.generator.NoiseSetting;
import com.miyake.dsp.generator.PulseGenerator;
import com.miyake.dsp.generator.PulseSetting;
import com.miyake.dsp.generator.SineSetting;
import com.miyake.dsp.otdr.FiberNode;
import com.miyake.dsp.otdr.OtdrSetting;
import com.thoughtworks.xstream.XStream;

public class FlowPersistenceImplXml implements FlowPersistence {
	private DspCompositeUiFactory factory;
	
	@Override
	public void save(String name, DspCompositeUI ui, DspCompositeUiFactory factory) {
		
		DspComposite composite = ui.getComposite();
		List<Object> list = new ArrayList<Object>();
		list.add(factory);
	
		DspComposite c = composite;
		while (true) {
			list.add(c.getSetting());
			
			if (c.getList().size() > 0) {
				c = c.getList().get(0);
			}
			else {
				break;
			}
		}
		
		XStream xstream = new XStream();
    	xstream.omitField(FilterSetting.class, "handlers");
    	xstream.omitField(ConvolutionSetting.class, "entryPoint");
    	xstream.omitField(OtdrSetting.class, "entryPoint");
    	
    	String xml = xstream.toXML(list);
    	try {
			BufferedWriter writeFile = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(name)));
			writeFile.write(xml);
			writeFile.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
	    }
	}

	@Override
	public DspCompositeUI load(String name) {
		XStream xstream = new XStream();
		BufferedReader reader = null;
		String tmp = null;
		String xml2 = "";
		
		DspCompositeUI entryPoint = null;
		
		try {
			reader = new BufferedReader(new InputStreamReader(new FileInputStream(name)));
			
			while((tmp = reader.readLine()) != null) {
				xml2 += tmp;
			}
			List<Object> list = (List<Object>) xstream.fromXML(xml2);
			Iterator<Object> it = list.iterator();
			DspCompositeUiFactory factory = (DspCompositeUiFactory) it.next();
			entryPoint = this.createUI(it.next(), factory);
			DspCompositeUI current = entryPoint;
			while(it.hasNext()) {
				DspCompositeUI next = createUI(it.next(), factory);
				current.add(next);
				current = next;
			}
			
			reader.close();
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();		
		} catch (IOException e) {
			e.printStackTrace();
		} 
		
		return entryPoint;
	}

	private DspCompositeUI createUI(Object c, DspCompositeUiFactory factory) {
		DspCompositeUI ui = null;
		
		if (c instanceof FftSetting) {
			ui = factory.createFFT();
		}
		else if (c instanceof AbsoluteSetting) {
			ui = factory.createAbsolute();
		}
		else if (c instanceof DiffSetting) {
			ui = factory.createDiff();
		}
		else if (c instanceof LogSetting) {
			ui = factory.createLog((LogSetting)c);
		}
		else if (c instanceof NormalizeSetting) {
			ui = factory.createNormalize();
		}
		else if (c instanceof OffsetSetting) {
			ui = factory.createOffset((OffsetSetting)c);
		}
		else if (c instanceof ConvolutionSetting) {
			ConvolutionSetting s = (ConvolutionSetting)c;
			DspCompositeUI entry = null;
			for (Object o : s.getSettingList()) {
				DspCompositeUI u = createUI(o, factory);
				if (entry == null) {
					entry = u;
				}
			}
			ui = factory.createConvolution(entry);
		}
		else if (c instanceof FilterSetting) {
			ui = factory.createFilter((FilterSetting)c);
		}
		else if (c instanceof NoiseSetting) {
			ui = factory.createNoiseGenerator((NoiseSetting)c);
		}
		else if (c instanceof PulseSetting) {
			ui = factory.createPulseGenerator((PulseSetting)c);
		}
		else if (c instanceof SineSetting) {
			ui = null;
		}
		else if (c instanceof OtdrSetting) {
			ui = factory.createOTDR(new OtdrSetting(1550, 20));
		}
		else if (c instanceof LimiterSetting) {
			ui = factory.createLimiter((LimiterSetting)c);
		}
		else if (c instanceof RcSetting) {
			ui = factory.createRC((RcSetting)c);
		}
		return ui;
	}

}
